﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.Xml;
using System.IO;
using SPVisualDev.Services;
using SPVisualDev.VSAddin.Services;
using EnvDTE80;

namespace SPVisualDev.VSAddin
{
    public class SpecialSolution : IDisposable
    {
        private Solution2 m_solution;
        private XmlDocument m_user_settings_xml;
        private MainServiceWrapper m_service_proxy;
        private ConnectionDetailsStruct m_remote_connection;
        private DTE2 m_dte;
        private Dictionary<string, SpecialProject> m_projects = new Dictionary<string, SpecialProject>();
        private bool m_connection_initialized;

        public SpecialSolution(Solution2 solution)
        {
            if (solution == null)
                return;

            m_solution = solution;
            m_dte = solution.DTE as DTE2;

            if (string.IsNullOrEmpty(solution.FullName))
                return;

            LoadSettings();
        }

        public void Dispose()
        {
            if (m_service_proxy != null)
            {
                m_service_proxy.Dispose();
            }
        }

        public DTE DTE
        {
            get { return m_solution.DTE; }
        }

        public IMainService ServiceProxy
        {
            get
            {
                if (m_service_proxy == null)
                {
                    m_remote_connection = Common.GetServiceConnectionBySolution(this);

                    m_service_proxy = new MainServiceWrapper(m_remote_connection);
                }

                return m_service_proxy.ServiceProxy;
            }
        }

        public void ReloadServiceProxy()
        {
            if (m_service_proxy != null)
            {
                m_service_proxy.Dispose();
                m_service_proxy = null;
            }

            foreach (KeyValuePair<string, SpecialProject> kvp in m_projects)
            {
                kvp.Value.ReloadServiceProxy();
            }

            m_remote_connection = Common.GetServiceConnectionBySolution(this);
        }

        public int Count
        {
            get { return m_projects.Keys.Count; }
        }

        public List<SpecialProject> GetAllSpecialProjects()
        {
            List<SpecialProject> list = new List<SpecialProject>();
            foreach (KeyValuePair<string, SpecialProject> kvp in m_projects)
            {
                list.Add(kvp.Value);
            }

            return list;
        }

        public SpecialProject GetSpecialProject(Project project)
        {
            if (project == null)
                return null;

            if (m_projects.ContainsKey(project.Name))
            {
                return m_projects[project.Name];
            }
            else
            {
                if (Common.CheckIfSpecialProject(project))
                {
                    SpecialProject specialProject = new SpecialProject(project, this);
                    m_projects.Add(project.Name, specialProject);

                    return specialProject;
                }
                else
                {
                    return null;
                }
            }
        }

        public void RemoveSpecialProject(Project project)
        {
            RemoveSpecialProject(project.Name);
        }

        public void RemoveSpecialProject(string projectName)
        {
            if (m_projects.ContainsKey(projectName))
            {
                m_projects[projectName].Dispose();
                m_projects.Remove(projectName);
            }
        }

        public string GetUserSettingsValue(string Key)
        {
            if (m_user_settings_xml == null)
                LoadSettings();

            XmlNode xn = m_user_settings_xml.DocumentElement.SelectSingleNode(Key);
            if (xn != null)
                return xn.InnerText;
            else
                return null;
        }

        public void SetUserSettingsValue(string Key, string Value, bool WriteImmediately)
        {
            if (Value == null)
                Value = string.Empty;

            if (m_user_settings_xml == null)
            {
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.LoadXml("<Settings></Settings>");

                m_user_settings_xml = xmldoc;
            }

            XmlNode xn = m_user_settings_xml.DocumentElement.SelectSingleNode(Key);
            if (xn != null)
                xn.InnerText = Value;
            else
            {
                XmlElement el = m_user_settings_xml.CreateElement(Key);
                el.InnerText = Value;
                m_user_settings_xml.DocumentElement.AppendChild(el);
            }

            if (WriteImmediately)
            {
                SaveSettings();
            }
        }

        public void LoadSettings()
        {
            if (m_solution == null)
                throw new NullReferenceException("No project assigned.");

            if (string.IsNullOrEmpty(m_solution.FullName))
            {
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.LoadXml("<Settings></Settings>");

                m_user_settings_xml = xmldoc;

                return;
            }

            string settings_file = Path.GetDirectoryName(m_solution.FullName) + "\\" + Common.C_SOLUTION_SETTINGS_FILE;
            try
            {
                XmlDocument xmldoc = new XmlDocument();

                if (!File.Exists(settings_file))
                {
                    xmldoc.LoadXml("<Settings></Settings>");
                    //xmldoc.Save(settings_file);
                }
                else
                {
                    xmldoc.Load(settings_file);
                }

                m_user_settings_xml = xmldoc;
            }
            catch (Exception ex)
            {
                throw new Exception("Failed to create load settings file at " + settings_file + ". " + ex.Message);
            }
        }

        public void SaveSettings()
        {
            if (m_solution == null)
                throw new NullReferenceException("No project assigned.");

            if (string.IsNullOrEmpty(m_solution.FullName))
                return;

            if (m_user_settings_xml == null)
            {
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.LoadXml("<Settings></Settings>");

                m_user_settings_xml = xmldoc;
            }

            string settings_file = Path.GetDirectoryName(m_solution.FullName) + "\\" + Common.C_SOLUTION_SETTINGS_FILE;
            try
            {
                m_user_settings_xml.Save(settings_file);

            }
            catch (Exception ex)
            {
                throw new Exception("Failed to create save settings file at " + settings_file + ". " + ex.Message);
            }
        }

        public bool UseRemoteServer
        {
            get
            {
                if (GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USE) == "True")
                    return true;
                else
                    return false;
            }
        }

        public bool UseService
        {
            get
            {
                if (UseRemoteServer || this.RemoteConnection.Port != 0)
                    return true;
                else
                    return false;
            }
        }

        public ConnectionDetailsStruct RemoteConnection
        {
            get
            {
                if (!m_connection_initialized)
                {
                    m_remote_connection = Common.GetServiceConnectionBySolution(this);
                    m_connection_initialized = true;
                }

                return m_remote_connection;
            }
        }
    }
}
